/**
 * Copyright (c) [2021-2021] [libbylg@126.com]
 * [lplogger] is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL
 * v2. You may obtain a copy of Mulan PSL v2 at:
 *             http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more
 * details.
 */
#ifndef LP_BUFFER_H
#define LP_BUFFER_H

#include "lp_logger.h"

#include "lp_asserts.h"

#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

LPEXTERN struct lp_buffer_t* lp_new_buffer(int32_t init_cap) {
    struct lp_buffer_t* buffer = (struct lp_buffer_t*)malloc(sizeof(struct lp_buffer_t));
    if (buffer == NULL) {
        ASSERT(false);
        return NULL;
    }

    if (init_cap < 0) {
        init_cap = LP_BUFFER_CAP_MIN;
    }

    buffer->data = (char*)malloc(init_cap * sizeof(char));
    if (buffer->data == NULL) {
        ASSERT(false);
        free(buffer);
        return NULL;
    }

    buffer->len = 0;
    buffer->cap = init_cap;

    return buffer;
}

LPEXTERN struct lp_buffer_t* lp_init_buffer(struct lp_buffer_t* buffer, int32_t init_cap) {
    if (init_cap < 0) {
        init_cap = LP_BUFFER_CAP_MIN;
    }

    buffer->data = (char*)malloc(init_cap * sizeof(char));
    if (buffer->data == NULL) {
        ASSERT(false);
        free(buffer);
        return NULL;
    }

    buffer->len = 0;
    buffer->cap = init_cap;

    return buffer;
}

LPEXTERN void lp_del_buffer(struct lp_buffer_t* buffer) {
    if (buffer == NULL) {
        ASSERT(false);
        return;
    }

    if (buffer->data != NULL) {
        free(buffer->data);
    }

    free(buffer);
}

LPEXTERN int lp_reserve_buffer(struct lp_buffer_t* buffer, int32_t new_cap) {
    if (buffer == NULL) {
        ASSERT(false);
        return -1;
    }

    if (new_cap < 0) {
        return -1;
    }

    if (new_cap < buffer->cap) {
        return 0;
    }

    char* old_data = buffer->data;
    char* new_data = (char*)malloc(new_cap * sizeof(char*));
    if (new_data == NULL) {
        return -1;
    }

    if (buffer->len > 0) {
        memcpy(new_data, buffer->data, buffer->len);
    }

    free(old_data);
    buffer->data = new_data;
    return 0;
}

#endif // LP_BUFFER_H
